#ifndef _OPERATOR_H_
#define _OPERATOR_H_

#include <QString>
#include <QWebElement>
#include <QWebElementCollection>
#include <QTimer>
#include <string>

#include "webpage.h"

// 3 min
#define PAGE_DEFAULT_DESTROY_TIME_MS (1000 * 60 * 3)

class WebSpiderRequestManager;
class WebSpiderRequest;
class OperatorDestroyChecker;
class WebSpiderDownloadRequest;

class Operator: public QObject {
    Q_OBJECT
    public:
        Operator(WebPage* page, WebSpiderRequest *req, QObject *parent = 0);
        ~Operator();

        WebSpiderRequest *request();

        /*
         * old function
         */
        QString title();
        QString frameTitle();
        QString getUrl();
        QString frameUrl();
        QString toHtml();
        bool loading();
        int loadingProgress();
        void reload();
        void goBack();
        void goForward();

        void setParseSuccess();
        void clearParseSuccess();
        bool isParseSuccess(); 

        bool destroying();
        void remove();

        // css selector
        QWebElementCollection findElements(QString selectorQuery);
        QWebElement findElement(QString selectorQuery);

        QString getText(QWebElement &element);
        QString getAttribute(QWebElement &element, QString attr);
        void setAttribute(QWebElement &element, QString attr, QString value);
        QString getInnerXml(QWebElement &element);
        QString getOuterXml(QWebElement &element);

        // action
        void setViewportSize(int w, int h);
        void click(QWebElement &element);

		/*
		 *  load functiong
		 */
        void loadUrl ( const QString &address,
                       const QString &operation,
                       const QMap<QString, QString> &headers,
                       QString bodyString = QString(),
                       QString encoding = QString(),
                       int timeout = 0, 
                       int dtimeout = 0
                     );

        void setHtml(const QString &html, const QString &url);
		void setSetting(const QString &name, const QString &setting);

        /*
         * webdriver like function
         */
        bool setDatabaseEnabled(long ref, bool enable);
        QString getTitle(long ref);
        QString renderTreeDump(long ref);
        QString getDomTreeSource(long ref);
        QString getPageSource(long ref);
        QString getUrl(long ref);

        /*
        bool isJavascriptEnabled(long ref);
        void setJavascriptEnabled(long ref, bool enable);
        object evaluateJS(object driver, long ref, objectArray arguments);
        */

        //Document
        long getElementById(long ref, QString query);

        long setCookies(long ref, const QVariantList &cookies);
        QVariantList cookies(long ref);
        long deleteCookie(long ref, QString cName);

        //Node
        QList<long> getElementsByTagName(long ref, QString query);

        QList<long> getElementsByName(long ref, QString query);

        // we don't want to implement it.
        QList<long> getElementsByXpath(long ref, QString query);

        long getElementByCssSelector(long ref, QString query);
        QList<long> getElementsByCssSelector(long ref, QString query);

        //Element
        QList<long> getChildsByCssSelector(long ref, QString query);
        QString getTagName(long ref);

        QString getAttribute(long ref, QString name);
        void setAttribute(long ref, QString name, QString value);
        void removeAttribute(long ref, QString name);

        QString getProperty(long ref, QString name);

        QString getText(long ref);

        QString getValue(long ref);

        long type(long ref, QString val);
        long sendKeys(long ref, QString type, long keys, int timeout = 0, int dtimeout = 0, WebSpiderSyncRequest *req = NULL);

        long setValue(long ref, QString val);

        void goBack(long ref);
        void goForward(long ref);
        long refresh(long ref);

        long submit(long ref);
        long click(long ref, int timeout = 0, int dtimeout = 0, WebSpiderSyncRequest *req = NULL);
        void mouseMove(int x, int y);
        void mouseMove(long ref);
        long download(long ref, WebSpiderDownloadRequest *req);
        long reset(long ref);
        long toggle(long ref);
        long focus(long ref);
        long selected(long ref);
        long setSelected(long ref, bool selected);
		long checked(long ref);
		long setChecked(long ref, bool checked);
        long selectOptionByIndex(long ref, long index);
        long stale(long ref);
        long activeElement();
        long selectFrameByName(QString name);
        long selectFrameByIdx(long idx);
        bool isVisible(long ref);
        long drag(long ref, int toX, int toY, int duration);
        QRect getRect(long ref);
        QString getAlertText(long ref, bool clr);

        QString getInnerXml(long ref);
        QString getOuterXml(long ref);

        void scroll(int x, int y);

        void setFilterRule(QList<QString> rules);
        void appendFilterRule(QString rule);
        void removeFilterRule(QString rule);
        bool matchFilter(QString resource);

        QString renderBase64();
        QString renderBase64(long ref);

        void setSelfDestroyTime(long timeMS);

        bool loadSuccess();
        void setLoadSuccess();
        void clearLoadSuccess();

        void setLastAlertString(QString str);

        void startSelfDestroyTimer();
        void startSelfDestroyTimer(long timeMs);

        void startTimeoutTimer();
        void startTimeoutTimer(long timeMs);
        void stopTimeoutTimer();

        void setHostNotFound();
        bool hostNotFound();

        void setHTTPRequestCanceled();
        bool httpRequestCanceled();

        bool protocolUnknown();
        void setProtocolUnknown();

        void setRawPageFlag();
        long rawPageFlag();

        void setRawRequest(WebSpiderSyncRequest* request);
        WebSpiderSyncRequest* rawRequest();

        void setNetWorkError();
        bool netWorkError();

        void setErrorCode(int errorCode);
        int errorCode();

        // async load flag is for function loadUrl
        void setSyncLoad();
        void clearSyncLoad();
        bool syncLoad();

        void dispatchActiviteDestoryEvent();

        long selfDestroyTime();
        long timeoutTime();

        void setTimeout();
        bool isTimeout();

        void setParsed();
        void clearParsed();
        bool hasParsed();

        void setPostData(QString data);
        void setMethod(QString method);

        QString postData();
        QString method();

        void release();

        void setDownloadRequest(WebSpiderDownloadRequest *req);
        WebSpiderDownloadRequest* getDownloadRequest();
        void clearDownloadRequest();

        std::string clientID();

    Q_SIGNALS:
        void didLaterParse();
        void didSelfDestroyParse();
        void didTimeout();

    private:
        void destory();

    private Q_SLOTS:
        void selfDestroy();
        void onTimeout();
        
    private:
        WebPage* m_page;
        bool m_parseSuccess;
        QTimer m_selfDestroyTimer;
        QTimer m_timeoutTimer;
        WebSpiderRequestManager *m_requestManager;
        int m_reloadTimes;
        WebSpiderRequest *m_request;
        WebSpiderDownloadRequest *m_downloadRequest;
        long m_thisPoint;
        bool m_loadSucess;
        bool m_destroying;
        OperatorDestroyChecker *m_destroyChecker;

        QList<QWebElement*> m_elementParms;
        QList<QWebElementCollection*> m_elementCollectionParms;

        QString m_lastAlertString;

        bool m_hostNotFound;
        bool m_HTTPRequestCanceled;
        bool m_netWorkError;
        bool m_protocolUnknown;
        bool m_syncLoad;
        bool m_isTimeout;
        bool m_hasParsed;
        int m_errorCode;

        QString m_postData;
        QString m_method;
};

#endif

